home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 31
/
Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso
/
Aminet
/
dev
/
c
/
vbccm68ksrc.lha
/
vbcc
/
vlink
/
support.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-03-07
|
11KB
|
492 lines
/* $VER: vlink support.c V0.5e (05.10.98)
*
* This file is part of vlink, a portable linker for multiple
* object formats.
* Copyright (c) 1997-99 Frank Wille
*
* vlink is freeware and part of the portable and retargetable ANSI C
* compiler vbcc, copyright (c) 1995-99 by Volker Barthelmann.
* vlink may be freely redistributed as long as no modifications are
* made and nothing is charged for it. Non-commercial usage is allowed
* without any restrictions.
* EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
* SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
*
*
* v0.5e (05.10.98) phx
* insertnode() is now insertbehind(). New functions insertbefore()
* and addhead().
* v0.5d (22.08.98) phx
* Faster allocation routines using large memory chunks. They must
* be activated by #define FASTALLOC.
* v0.3 (12.04.98) phx
* Replaced l2bh(),l2bw(),read16(),read32(),write16(),write32()
* by swap16(),swap32(),read16sw(),read32sw(),write16sw(),write32sw().
* fwrite32() is now called fwrite32be().
* v0.2 (07.03.98) phx
* insertnode().
* v0.1 (27.02.98) phx
* First version that seems to link AmigaOS ADOS and EHF
* objects and libraries. Many common features, like linking
* sections together which have relative references, are
* still missing. Also, PowerPC-ELF32 support is about to come.
* v0.0 (04.08.97) phx
* File created. Project started on a beautiful summer-day
* at the North Sea beach of Cuxhaven. :)
* This file is based on support.c v0.4 of the portable
* PowerPC assembler "pasm".
*/
#define SUPPORT_C
#include "vlink.h"
void *alloc(size_t);
void *alloczero(size_t);
char *allocstring(char *);
void *alloc_hashtable(size_t);
void initlist(struct list *);
void insertbefore(struct node *,struct node *);
void insertbehind(struct node *,struct node *);
void addhead(struct list *,struct node *);
void addtail(struct list *,struct node *);
struct node *remhead(struct list *);
struct node *remnode(struct node *);
char *mapfile(char *);
char *base_name(char *);
char *check_name(char *);
int checkrange(uint32,int,bool);
uint16 swap16(uint16);
uint32 swap32(uint32);
uint16 read16sw(uint8 *);
uint32 read32sw(uint8 *);
void write16sw(uint8 *,uint16);
void write32sw(uint8 *,uint32);
void fwritex(FILE *,void *,size_t);
void fwrite32be(FILE *,uint32);
void fwrite_align(FILE *,uint32,uint32);
unsigned long elf_hash(unsigned char *);
unsigned long align(unsigned long,unsigned long);
int shiftval(uint32);
static size_t filesize(FILE *,char *);
static char *unnamed_txt = "unnamed";
#ifdef FASTALLOC
static struct MemChunk *new_chunk(void);
void init_mem(void);
#define CHUNKSIZE (0x40000-sizeof(void *)-sizeof(void *)-8)
struct MemChunk { /* Large memory chunks for faster allocation */
struct MemChunk *next;
unsigned char *ptr; /* pointer to available memory in this chunk */
uint32 free; /* number of bytes free */
#ifndef ALIGNOFF4
uint32 align; /* only for 64-bit alignment */
#endif
unsigned char mchunk[CHUNKSIZE];
};
static struct MemChunk *mem; /* first memory chunk for alloc() */
static struct MemChunk *new_chunk()
{
struct MemChunk *m;
if (!(m = (struct MemChunk *)malloc(sizeof(struct MemChunk))))
error(1); /* out of memory */
m->next = NULL;
m->ptr = m->mchunk;
m->free = CHUNKSIZE;
return (m);
}
void init_mem()
{
mem = new_chunk();
}
#endif
void *alloc(size_t size)
/* allocate memory and print error message if not enough available */
{
#ifdef FASTALLOC /* faster, but needs more memory */
struct MemChunk *m=mem,*n;
uint32 bytes;
void *p;
if (!(bytes = (uint32)(size+7) & ~7)) /* return 64-bit aligned memory */
bytes = 8;
if (bytes > CHUNKSIZE) {
/* get an own block, for so much memory */
if (!(p = malloc((size_t)bytes)))
error(1); /* out of memory */
return (p);
}
for (;;) {
if (bytes <= m->free) {
p = (void *)m->ptr;
m->free -= bytes;
m->ptr += bytes;
return (p);
}
if (!(n = m->next))
n = m->next = new_chunk();
m = n;
}
#else
void *p;
if (!size)
size = 1;
if (!(p = malloc(size)))
error(1); /* out of memory */
return (p);
#endif
}
void *alloczero(size_t size)
/* same as alloc() but zeroes the allocated memory */
{
void *p = alloc(size);
memset(p,0,size);
return (p);
}
char *allocstring(char *s)
/* allocate space for a single string */
/* @@@ this should be improved by some kind of string buffer */
{
char *p = alloc(strlen(s)+1);
strcpy(p,s);
return (p);
}
void *alloc_hashtable(size_t entries)
{
return (alloczero(entries * sizeof(void *)));
}
void initlist(struct list *l)
/* initializes a list structure */
{
l->first = (struct node *)&l->dummy;
l->dummy = NULL;
l->last = (struct node *)&l->first;
}
void insertbefore(struct node *n,struct node *sn)
/* insert node n directly before node sn */
/* sn must be a real node - no dummy nodes allowed! */
{
struct node *pn = sn->pred;
n->next = sn;
n->pred = pn;
pn->next = sn->pred = n;
}
void insertbehind(struct node *pn,struct node *n)
/* insert node n directly behind node pn */
/* pn must be a real node - no dummy nodes allowed! */
{
struct node *sn = pn->next;
n->next = sn;
n->pred = pn;
pn->next = sn->pred = n;
}
void addhead(struct list *l,struct node *n)
/* add node as first element of list */
{
struct node *fn = l->first;
n->pred = fn->pred;
fn->pred = n;
n->next = fn;
l->first = n;
}
void addtail(struct list *l,struct node *n)
/* add node as last element of list */
{
struct node *ln = l->last;
n->next = ln->next;
ln->next = n;
n->pred = ln;
l->last = n;
}
struct node *remhead(struct list *l)
/* remove first node in list and return a pointer to it */
{
struct node *n = l->first;
if (n->next) {
l->first = n->next;
n->next->pred = n->pred;
return (n);
}
return (NULL);
}
struct node *remnode(struct node *n)
/* remove a node from a list */
{
n->next->pred = n->pred;
n->pred->next = n->next;
return (n);
}
char *mapfile(char *name)
/* map a complete file into memory and return its address */
/* the file's length is returned in *(p-sizeof(size_t)) */
{
FILE *fp;
char *p=NULL;
size_t fsiz;
if (fp = fopen(name,"r")) {
fsiz = filesize(fp,name);
p = alloc(fsiz+sizeof(size_t));
*(size_t *)p = fsiz; /* store file size before the text starts */
p += sizeof(size_t);
if (fread(p,1,fsiz,fp) != fsiz) {
fclose(fp);
error(7,name); /* read error */
}
fclose(fp);
}
return (p);
}
static size_t filesize(FILE *fp,char *name)
{
/* somebody knows a better way to determine file size in ANSI C? */
long oldpos,size;
if ((oldpos = ftell(fp)) >= 0)
if (fseek(fp,0,SEEK_END) >= 0)
if ((size = ftell(fp)) >= 0)
if (fseek(fp,oldpos,SEEK_SET) >= 0)
return ((size_t)size);
fclose(fp);
error(5,name); /* read error - doesn't return */
}
char *base_name(char *s)
/* returns last part of a path - the file name itself */
{
char c;
int l = strlen(s);
while (l--) {
c = s[l];
if (c== '/' || c==':')
return (&s[l+1]);
}
return (s);
}
char *check_name(char *name)
/* returns "unnamed", if name is a NULL-pointer */
{
if (name)
return (name);
return (unnamed_txt);
}
int checkrange(uint32 val,int size,bool sign)
/* Checks if an integer value is in range, size=3 means 26-bit (B-instr.) */
/* If the check fails, the number of bits is returned (8, 16, 26) */
{
if (sign) {
int32 sval = (int32)val;
switch (size) {
case 1:
if (sval>0x7f || sval<-0x80)
return (8);
break;
case 2:
if (sval>0x7fff || sval<-0x8000)
return (16);
break;
case 3:
if (sval>0x1ffffff || sval<-0x2000000)
return (26);
break;
}
}
else {
switch (size) {
case 1:
if (val>0xff)
return (8);
break;
case 2:
if (val>0xffff)
return (16);
break;